﻿// <copyright file="DesktopNewGameViewModelTests.cs" company="Mooville">
//   Copyright © 2010 Roger Deetz. All rights reserved.
// </copyright>

namespace Mooville.QUno.ViewModel.Tests
{
    using System;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Mooville.QUno.Model;
    using Mooville.QUno.ViewModel;

    [TestClass]
    public class DesktopNewGameViewModelTests
    {
        [TestMethod]
        public void Constructor_GivenValues_ShouldNotThrow()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.IsNotNull(target);

            return;
        }

        [TestMethod]
        public void AfterConstructor_NumberOfPlayers_ShouldBeCorrect()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.AreEqual(2, target.Players.Count());

            return;
        }

        [TestMethod]
        public void AfterConstructor_HumanPlayerName_ShouldBeCorrect()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.AreEqual("Roger", target.HumanPlayerName);

            return;
        }

        [TestMethod]
        public void AfterConstructor_NumberOfComputerPlayers_ShouldBeCorrect()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.AreEqual(1, DesktopNewGameViewModelTests.CountComputerPlayers(target));

            return;
        }

        [TestMethod]
        public void AfterConstructor_CurrentComputerPlayer_ShouldNotBeNull()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.IsNotNull(target.ComputerPlayers.CurrentItem);

            return;
        }

        [TestMethod]
        public void CanAddComputerPlayer_ShouldBeTrue()
        {
            // This may change if we implement the logic for enforcing the maximum number of players.
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.IsTrue(target.CanAddComputerPlayer);

            return;
        }

        [TestMethod]
        public void WithComputerPlayers_CanRemoveComputerPlayer_ShouldBeTrue()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.IsTrue(target.CanRemoveComputerPlayer);

            return;
        }

        [TestMethod]
        public void WithNoComputerPlayers_CanRemoveComputerPlayer_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 0, "Player {0}");
            Assert.IsFalse(target.CanRemoveComputerPlayer);

            return;
        }

        [TestMethod]
        public void AfterRemovingAllComputerPlayers_CurrentComputerPlayer_ShouldBeNull()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.RemoveComputerPlayer(target.ComputerPlayers.CurrentItem as Player);
            Assert.IsNull(target.ComputerPlayers.CurrentItem);

            return;
        }

        [TestMethod]
        public void AfterRemovingAllComputerPlayers_CanRemoveComputerPlayer_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.RemoveComputerPlayer(target.ComputerPlayers.CurrentItem as Player);
            Assert.IsFalse(target.CanRemoveComputerPlayer);

            return;
        }

        [TestMethod]
        public void AddComputerPlayer_ShouldAddPlayer()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.AddComputerPlayer();
            Assert.AreEqual(2, DesktopNewGameViewModelTests.CountComputerPlayers(target));

            return;
        }

        [TestMethod]
        public void RemoveComputerPlayer_ShouldRemovePlayer()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 2, "Player {0}");
            target.RemoveComputerPlayer(target.ComputerPlayers.CurrentItem as Player);
            Assert.AreEqual(1, DesktopNewGameViewModelTests.CountComputerPlayers(target));

            return;
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RemoveComputerPlayer_GivenNull_ShouldThrow()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.RemoveComputerPlayer(null);

            return;
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RemoveComputerPlayer_WhenNoComputerPlayers_ShouldThrow()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 0, "Player {0}");
            target.RemoveComputerPlayer(new Player());

            return;
        }

        [TestMethod]
        public void AfterConstructor_CanStartGame_ShouldBeTrue()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            Assert.IsTrue(target.CanStartGame);

            return;
        }

        [TestMethod]
        public void CanStartGame_WithEmptyHumanPlayerName_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.HumanPlayerName = String.Empty;
            Assert.IsFalse(target.CanStartGame);

            return;
        }

        [TestMethod]
        public void CanStartGame_WithNullHumanPlayerName_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.HumanPlayerName = null;
            Assert.IsFalse(target.CanStartGame);

            return;
        }

        [TestMethod]
        public void CanStartGame_WithWhitespaceHumanPlayerName_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.HumanPlayerName = " ";
            Assert.IsFalse(target.CanStartGame);

            return;
        }

        [TestMethod]
        public void CanStartGame_WithNoComputerPlayers_ShouldBeFalse()
        {
            DesktopNewGameViewModel target = new DesktopNewGameViewModel("Roger", 1, "Player {0}");
            target.RemoveComputerPlayer(target.ComputerPlayers.CurrentItem as Player);
            Assert.IsFalse(target.CanStartGame);

            return;
        }

        private static int CountComputerPlayers(DesktopNewGameViewModel target)
        {
            int numberOfComputerPlayers = 0;

            foreach (var item in target.ComputerPlayers)
            {
                numberOfComputerPlayers++;
            }

            return numberOfComputerPlayers;
        }
    }
}
